# Z-Image-Turbo on AMD BC-250 — Setup Documentation

## Overview

**Z-Image-Turbo** image generation server running on **AMD BC-250** (GFX1013 RDNA2, 24 CUs) via **Vulkan** (RADV/Mesa) on **CachyOS**.

| Component | Detail |
|-----------|--------|
| **GPU** | AMD BC-250 — 24 CUs, GFX1013 RDNA2, 16 GB shared GDDR6 |
| **Driver** | RADV (Mesa 25.3.4) via Vulkan 1.4.335 |
| **Backend** | Vulkan only (no ROCm) |
| **Server** | [stable-diffusion.cpp-restapi](https://github.com/fszontagh/stable-diffusion.cpp-restapi) |
| **OS** | CachyOS (Arch-based) |

## Models

| Model | File | Size | Location |
|-------|------|------|----------|
| Z-Image-Turbo | `z_image_turbo-Q5_K_S.gguf` | 4.9 GB | `~/sd-models/diffusion_models/` |
| Qwen3-4B Instruct | `Qwen3-4B-Instruct-2507-Q5_K_S.gguf` | 2.8 GB | `~/sd-models/llm/` |
| FLUX VAE | `ae.safetensors` | 320 MB | `~/sd-models/vae/` |

## Directory Structure

```
~/
├── stable-diffusion.cpp-restapi/
│   └── build/
│       ├── bin/sdcpp-restapi          # Server binary (80 MB)
│       ├── config.json                # Server configuration
│       └── webui/                     # Vue.js WebUI
├── sd-models/
│   ├── diffusion_models/              # Main diffusion model GGUFs (Z-Image)
│   ├── checkpoints/                   # Legacy checkpoint models
│   ├── vae/                           # VAE models
│   ├── llm/                           # LLM models (prompt enhancement)
│   ├── lora/                          # LoRA adapters
│   ├── clip/                          # CLIP models
│   ├── t5/                            # T5 text encoders
│   ├── embeddings/                    # Textual inversions
│   ├── controlnet/                    # ControlNet models
│   ├── esrgan/                        # Upscaler models
│   └── taesd/                         # Tiny AutoEncoder models
├── sd-outputs/                        # Generated images
├── start-zimage.sh                    # Quick start script
└── .config/systemd/user/
    └── zimage.service                 # Systemd user service
```

## Quick Start

```bash
# Option 1: Manual start
~/start-zimage.sh

# Option 2: Systemd service
systemctl --user start zimage
```

Then open: **http://localhost:8080/ui**

## Usage

### WebUI

1. Open http://localhost:8080/ui
2. Go to **Models** → select `z_image_turbo-Q5_K_S.gguf`
3. Set VAE to `ae.safetensors`, LLM to `Qwen3-4B-Instruct-2507-Q5_K_S.gguf`
4. First load takes 20–40 seconds
5. Settings: **Steps 8**, **CFG 1.0**, **Euler** sampler
6. Start with 512×512 (~37 s), then try 1024×1024 (~80 s)

### API — Load Model

```bash
curl -X POST http://localhost:8080/models/load \
  -H "Content-Type: application/json" \
  -d '{
    "model_name": "z_image_turbo-Q5_K_S.gguf",
    "model_type": "diffusion",
    "vae": "ae.safetensors",
    "llm": "Qwen3-4B-Instruct-2507-Q5_K_S.gguf"
  }'
```

### API — Generate Image (512×512)

```bash
curl -X POST http://localhost:8080/txt2img \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "astronaut on mars, cinematic",
    "width": 512,
    "height": 512,
    "steps": 8,
    "cfg_scale": 1.0,
    "sampler_name": "euler",
    "scheduler": "smoothstep",
    "seed": -1
  }' --output image.png
```

## Systemd Service

```bash
# Enable auto-start on login
systemctl --user enable zimage

# Start / stop / restart
systemctl --user start zimage
systemctl --user stop zimage
systemctl --user restart zimage

# View logs
journalctl --user -u zimage -f
```

## Vulkan Environment Variables

| Variable | Value | Purpose |
|----------|-------|---------|
| `AMD_VULKAN_ICD` | `RADV` | Use Mesa RADV driver |
| `GGML_VK_FORCE_MAX_ALLOCATION_SIZE` | `536870912` | 512 MB max alloc (OOM prevention) |
| `RADV_PERFTEST` | `nggc` | NGG culling compute boost |

## Troubleshooting

### Slow generation (>20s at 1024×1024)
```bash
# Check logs for allocation failures
journalctl --user -u zimage -f

# Try reducing max allocation to 256 MB
export GGML_VK_FORCE_MAX_ALLOCATION_SIZE=268435456

# Try AMDVLK instead of RADV
sudo pacman -S amdvlk
export AMD_VULKAN_ICD=AMDVLK
```

### Vulkan not detecting GPU
```bash
# Verify Vulkan
vulkaninfo --summary | grep BC-250

# Force ICD file path
VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/radeon_icd.x86_64.json vulkaninfo
```

### Out of Memory (OOM)
- Use Q3_K_S quantization (smaller model)
- Set `batch_count: 1` in generation requests
- Reduce resolution to 512×512

### Monitor GPU
```bash
# GPU utilization
watch radeontop

# VRAM usage
cat /sys/class/drm/card0/device/mem_info_vram_used
```

## Build from Source (Reference)

```bash
cd ~/stable-diffusion.cpp-restapi
mkdir -p build && cd build
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DSD_VULKAN=ON -DSDCPP_WEBUI=ON
ninja -j$(nproc --all)
```

## Performance Expectations

| Resolution | Expected Time | Notes |
|------------|--------------|-------|
| 512×512 | ~37 seconds | Q5_K_S, 8 steps, Euler, Vulkan |
| 512×1024 | ~80 seconds | Q5_K_S, 8 steps, Euler, Vulkan |
| 1024×1024 | ~150 seconds | Q5_K_S, 8 steps, Euler, Vulkan |
| First load | 20–40 seconds | One-time on startup |
